// Copyright 2010 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.android.apps.moderator;

/**
 * Contains vote bar logic to match the full website app
 */
public class VoteBar {

  /** Initial number of max votes for a widget. */
  private static final int MINIMUM_MAX_VOTES = 10;

  /**
   * Relative scaling factor for drawing bars.
   * This is the power vote counts are raised by when computing bar widths.
   *
   * SCALING_FACTOR | Effect
   *                |
   * 1              | Bar sizes are proportional to their number of votes.
   * 0.5            | Bar with 4 votes will be twice as wide as a bar with 1 vote.
   * 0.33           | Bar with 8 votes will be twice as wide as a bar with 1 vote.
   * 0              | All bars have the same size.
   */
  private static final double SCALING_FACTOR = 0.5;

  /**
   * Scales votes once MINIMUM_MAX_VOTES has been reached.
   */
  private static double calculateScaledVotes(int inputVotes) {
    int unscaledVotes = Math.min(MINIMUM_MAX_VOTES, inputVotes);
    int remainingVotes = Math.max(inputVotes - MINIMUM_MAX_VOTES, 0);
    return unscaledVotes + Math.pow(remainingVotes, SCALING_FACTOR);
  }

  /** Number of votes required to be 100% full. */
  private int maxVotes;

  /** Scaled maximum number of votes */
  private double scaledMaxVotes;

  /** Scaled number of votes */
  private double scaledVotes;

  /** Minimum number of votes to enable scaling. */
  private int scalingThreshold = 0;

  /** Current number of votes. */
  private int votes;

  private double width;

  protected VoteBar() {
    setMaxVotes(MINIMUM_MAX_VOTES);
  }

  public void decrement() {
    setVotes(votes - 1);
  }

  /**
   * Draws the bar based on the number of votes relative to maximum.
   */
  private void drawBar(double widthMultiplier) {
    this.width = Math.max(0, Math.min(widthMultiplier, 1.0f));
  }

  /**
   * Returns the current number of votes for the bar.
   */
  public int getVotes() {
    return votes;
  }

  public void increment() {
    setVotes(votes + 1);
  }

  /**
   * Number of votes needed to be considered 100%.
   */
  public void setMaxVotes(int max) {
    maxVotes = Math.max(max, MINIMUM_MAX_VOTES);
    scaledMaxVotes = calculateScaledVotes(maxVotes);
    setVotes(votes);
  }

  /**
   * Sets the minimum number of votes needed to enable scaling.
   */
  public void setScalingThreshold(int voteCount) {
    scalingThreshold = Math.max(0, voteCount);
  }

  /**
   * Current number of votes for the bar.
   */
  public void setVotes(int num) {
    votes = num;
    scaledVotes = calculateScaledVotes(votes);

    // Only use scaling if this is the biggest bar.
    if (votes >= scalingThreshold || scalingThreshold == 0) {
      drawBar(scaledVotes / scaledMaxVotes);
    } else {
      double biggestBarWidth = calculateScaledVotes(scalingThreshold) / scaledMaxVotes;
      drawBar((double) votes / scalingThreshold * biggestBarWidth);
    }
  }

  public double getWidth() {
    return width;
  }

}